package org.jeecg.eqp.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.StyleHelper;
import org.jeecg.eqp.entity.EqpSpchkheadValue;
import org.jeecg.eqp.mapper.EqpSpchkdetailValueMapper;
import org.jeecg.eqp.mapper.EqpSpchkheadValueMapper;
import org.jeecg.eqp.service.IEqpSpchkheadValueService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.eqp.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Description: 点检记录表
 * @Author: shaolong
 * @Date: 2022-10-13
 * @Version: V1.0
 */
@Service
public class EqpSpchkheadValueServiceImpl extends ServiceImpl<EqpSpchkheadValueMapper, EqpSpchkheadValue> implements IEqpSpchkheadValueService {

	private static final int MAX_PER_ROW = 3;          // 每行最多3个五万次区块
	private static final int BLOCK_ROWS = 3;           // 每个区块占3行
	private static final int DETAIL_START_ROW = 5;     // 明细数据起始行
	private static final int SERIALNO_START_ROW = 12;  // 五万次区块起始行
	private static final int TEMPLATE_STYLE_ROW = 5;  // 模板样式参考行


	@Autowired
	private EqpSpchkheadValueMapper eqpSpchkheadValueMapper;
	@Autowired
	private EqpSpchkdetailValueMapper eqpSpchkdetailValueMapper;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delMain(String id) {
		eqpSpchkdetailValueMapper.deleteByMainId(id);
		//把这里的删除给改了 改成按照id删
		Map<String, Object> map = new HashMap<>();
		map.put("REC_ID", id);
		eqpSpchkheadValueMapper.deleteByMap(map);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delBatchMain(Collection<? extends Serializable> idList) {
		for (Serializable id : idList) {
			eqpSpchkdetailValueMapper.deleteByMainId(id.toString());
			eqpSpchkheadValueMapper.deleteById(id);
		}
	}

	@Override
	public Result<String> edit(EqpSpchkheadValue eqpSpchkheadValue) {
		eqpSpchkheadValue.setCtime(new Date());
		LambdaUpdateWrapper<EqpSpchkheadValue> eq = new LambdaUpdateWrapper<EqpSpchkheadValue>();
		eq.eq(EqpSpchkheadValue::getRecId, eqpSpchkheadValue.getRecId());
		boolean update = update(eqpSpchkheadValue, eq);
		return update ? Result.ok("修改成功!") : Result.error("修改失败!");
	}

	@Override
	public IPage<EqpSpchkheadValueVO> getEqpRecordList(Page<EqpSpchkheadValueVO> page, EqpSpchkheadValueVO param) {
		return eqpSpchkheadValueMapper.getEqpRecordList(page,param);
	}

	@Override
	public List<EqpMaintainDetailVO> queryEqpDetailList(EqpSpchkheadValue eqpSpchkheadValue) {
		return eqpSpchkheadValueMapper.getEqpDetailList(eqpSpchkheadValue);
	}

	@Override
	public void exportExcel(List<EqpSpchkheadValue> headList, HttpServletResponse response)  {
		String serialno = headList.get(0).getSerialno();
		List<String> serialNos = new ArrayList<>();
		List<Integer> headIds = new ArrayList<>();
		List<EquipmentInfoVO> infos = new ArrayList<>();
		headList.forEach(head -> {
			serialNos.add(head.getSerialno());
			headIds.add(head.getRecId());
			EquipmentInfoVO info = eqpSpchkheadValueMapper.getEquipmentInfos(head.getSerialno(), head.getRecId());
			infos.add(info);
		});
//		List<EquipmentInfoVO> infos = eqpSpchkheadValueMapper.getEquipmentInfos(serialno);
		List<SpchkDetailVO> details = eqpSpchkheadValueMapper.getDetails(headIds);
		InputStream internalStream = null;
		// 优先尝试从 JAR 外部的 resources 目录加载
		try {
			File externalFile = new File("resources/template/spchk.xlsx");
			if (externalFile.exists()) {
				internalStream = new FileInputStream(externalFile);
			} else {
				internalStream = getClass().getClassLoader()
						.getResourceAsStream("template/spchk.xlsx");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		try (InputStream is = internalStream;
			 XSSFWorkbook workbook = new XSSFWorkbook(is)) {
			// 创建样式
			CellStyle centerStyle = workbook.createCellStyle();
			centerStyle.setAlignment(HorizontalAlignment.CENTER);
			centerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
			XSSFSheet sheet = workbook.getSheetAt(0);
			initSheetStyle(sheet);  // 初始化样式

			fillBasicInfo(sheet, infos.get(0), centerStyle);
			int currentRow = fillDynamicDetails(sheet, details, centerStyle);

			generateSerialBlocks(workbook, sheet, infos, currentRow, centerStyle);

			setFileName(response, infos.get(0));
			workbook.write(response.getOutputStream());
			workbook.close();
		} catch (IOException e) {
			handleExportError(e);
		}
    }

	private void initSheetStyle(XSSFSheet sheet) {
		// 设置默认列宽
		sheet.setDefaultColumnWidth(15);
		// 设置行高（示例值）
		sheet.getRow(TEMPLATE_STYLE_ROW).setHeightInPoints(40);
	}

	private void fillBasicInfo(XSSFSheet sheet, EquipmentInfoVO info,CellStyle centerStyle) {
		setCellValue(sheet, 1, 9, info.getLine(), centerStyle);     // 产线信息
		setCellValue(sheet, 3, 0, info.getOp(), centerStyle);       // 工站信息
		if (info.getType().equals("1")) {
			setCellValue(sheet, 3, 3, "设备", centerStyle);     // 工装类别
		} else if (info.getType().equals("2")) {
			setCellValue(sheet, 3, 3, "工装", centerStyle);     // 工装类别
		} else if (info.getType().equals("3")) {
			setCellValue(sheet, 3, 3, "夹具", centerStyle);     // 工装类别
		} else if (info.getType().equals("4")) {
			setCellValue(sheet, 3, 3, "设备位置", centerStyle);     // 工装类别
		} else {
			setCellValue(sheet, 3, 3, info.getType(), centerStyle);     // 工装类别
		}

		setCellValue(sheet, 3, 6, info.getSerialno(), centerStyle); // 模具编号
		setCellValue(sheet, 3, 9, info.getStn(), centerStyle);      // 使用工序描述
	}

	private int fillDynamicDetails(XSSFSheet sheet, List<SpchkDetailVO> details, CellStyle centerStyle) {
		int currentRow = DETAIL_START_ROW;
		for (SpchkDetailVO detail : details) {
			XSSFRow row = createRowWithStyle(sheet, currentRow, TEMPLATE_STYLE_ROW);
			// 合并标题行
			if (currentRow > 9) {
				mergeCells(sheet, currentRow, currentRow, 0, 2);
				mergeCells(sheet, currentRow, currentRow, 3, 5);
				mergeCells(sheet, currentRow, currentRow, 6, 11);
			}

			setCellValue(row, 0, detail.getName(), centerStyle);
			setCellValue(row, 3, detail.getNode(), centerStyle);
			setCellValue(row, 6, detail.getStandard(), centerStyle);
			currentRow++;
		}
		return currentRow;
	}

	private void generateSerialBlocks(XSSFWorkbook workbook, XSSFSheet sheet, List<EquipmentInfoVO> serialNos, int currentRow, CellStyle centerStyle) {
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		if (serialNos == null || serialNos.isEmpty()) return;

		int groupCount = 0;
		for (int i = 0; i < serialNos.size(); i++) {
			int positionInGroup = i % MAX_PER_ROW;

			// 每满3个开启新组
			if (positionInGroup == 0) {
				groupCount++;
			}
			String result = serialNos.get(i).getResult();
			int startRow = 0;
			if (currentRow > SERIALNO_START_ROW) {
				startRow = currentRow + (groupCount - 1) * BLOCK_ROWS;
			} else {
				startRow = SERIALNO_START_ROW + (groupCount - 1) * BLOCK_ROWS;
			}
//			int startRow = SERIALNO_START_ROW + (groupCount - 1) * BLOCK_ROWS;
			createSerialBlock(workbook, sheet, startRow, positionInGroup, sysUser.getUsername(), result, centerStyle);
		}

		// 处理最后一组未满的情况
		handleLastGroup(sheet, serialNos.size(), groupCount, currentRow);
	}

	private void createSerialBlock(XSSFWorkbook workbook, XSSFSheet sheet, int startRow,
								   int position, String userName, String result, CellStyle centerStyle) {
		int startCol = position * 4;

		// 创建三行区块
		XSSFRow titleRow = createRowWithStyle(sheet, startRow, TEMPLATE_STYLE_ROW);
		XSSFRow headerRow = createRowWithStyle(sheet, startRow + 1, TEMPLATE_STYLE_ROW);
		XSSFRow dataRow = createRowWithStyle(sheet, startRow + 2, TEMPLATE_STYLE_ROW);

		// 合并标题行
		mergeCells(sheet, startRow, startRow, startCol, startCol + 3);
		setCellValue(titleRow, startCol, "五万次", centerStyle);

		// 设置列标题
		setCellValue(headerRow, startCol, "合格", centerStyle);
		setCellValue(headerRow, startCol + 1, "不合格/修复", centerStyle);
		setCellValue(headerRow, startCol + 2, "保养日期", centerStyle);
		setCellValue(headerRow, startCol + 3, "检查人", centerStyle);

		// 填充数据
		if (result.equals("1")) {
			setCellValue(dataRow, startCol, "√", centerStyle);
			setCellValue(dataRow, startCol + 1, "", centerStyle);
		} else {
			setCellValue(dataRow, startCol, "X", centerStyle);
			setCellValue(dataRow, startCol + 1, "▲", centerStyle);
		}

		String dateStr = DateUtils.formatDate();
		setCellValue(dataRow, startCol + 2, dateStr, centerStyle);
		setCellValue(dataRow, startCol + 3, userName, centerStyle);

		// 设置日期格式
		CellStyle dateStyle = createDateStyle(workbook);
//		dataRow.getCell(startCol + 2).setCellStyle(dateStyle);
	}

	private void handleLastGroup(XSSFSheet sheet, int totalSize, int groupCount, int currentRow) {
		int remaining = totalSize % MAX_PER_ROW;
		if (remaining == 0) return;
		int lastGroupStart = 0;
		if (currentRow > SERIALNO_START_ROW) {
//			startRow = currentRow + (groupCount - 1) * BLOCK_ROWS;
			lastGroupStart = currentRow + (groupCount - 1) * BLOCK_ROWS;
		} else {
			lastGroupStart = SERIALNO_START_ROW + (groupCount - 1) * BLOCK_ROWS;
		}
//		int lastGroupStart = SERIALNO_START_ROW + (groupCount - 1) * BLOCK_ROWS;
		for (int i = remaining; i < MAX_PER_ROW; i++) {
			int startCol = i * 4;
			mergeCells(sheet, lastGroupStart, lastGroupStart, startCol, startCol + 3);
		}
	}

	private XSSFRow createRowWithStyle(XSSFSheet sheet, int rowNum, int styleRow) {
		XSSFRow row = sheet.getRow(rowNum) != null ? sheet.getRow(rowNum) : sheet.createRow(rowNum);
		if (rowNum > styleRow) {
			StyleHelper.cloneRowStyle(sheet.getWorkbook(), sheet.getRow(styleRow), row);
		}
		return row;
	}

	private CellStyle createDateStyle(XSSFWorkbook workbook) {
		CellStyle style = workbook.createCellStyle();
		CreationHelper createHelper = workbook.getCreationHelper();
		style.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-mm-dd"));
		return style;
	}

	private void mergeCells(XSSFSheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
		sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
	}

	private void setCellValue(XSSFSheet sheet, int rowNum, int col, Object value, CellStyle centerStyle) {
		XSSFRow row = sheet.getRow(rowNum) != null ? sheet.getRow(rowNum) : sheet.createRow(rowNum);
		setCellValue(row, col, value, centerStyle);
	}

	private void setCellValue(XSSFRow row, int col, Object value, CellStyle centerStyle) {
		Cell cell = row.getCell(col, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
		if (value instanceof Date) {
			cell.setCellValue((Date) value);
		} else if (value instanceof Number) {
			cell.setCellValue(((Number) value).doubleValue());
		} else {
			cell.setCellValue(value != null ? value.toString() : "");
		}
	}

	private void setFileName(HttpServletResponse response, EquipmentInfoVO info) throws UnsupportedEncodingException {
		String fileName = String.format("%s保养表%s.xlsx",
				info.getName(),
				new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
		// 设置响应头
		response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
		response.setHeader(
				HttpHeaders.CONTENT_DISPOSITION,
				ContentDisposition.attachment()
						.filename(fileName, StandardCharsets.UTF_8) // 自动处理编码问题
						.build().toString()
		);
//		String encodedName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
//		response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedName + "\"");
//		response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
	}

	private void handleExportError(Exception e) {
		log.error("Excel导出失败", e);
		throw new RuntimeException("导出失败，请检查模板格式或联系管理员");
	}
}
